package util

import (
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
)

func JsonValueToString(value interface{}) string {
	if value == nil {
		return ""
	}
	switch value := value.(type) {
	case string:
		return value
	default:
		return fmt.Sprintf("%v", value)
	}
}

func JsonValueToUint8(value interface{}) uint8 {
	switch value := value.(type) {
	case string:
		v, _ := strconv.ParseUint(value, 10, 8)
		return uint8(v)
	case float32:
		return uint8(value)
	case float64:
		return uint8(value)
	case uint8:
		return value
	case uint16:
		return uint8(value)
	case uint32:
		return uint8(value)
	case uint64:
		return uint8(value)
	}
	return 0
}

func JsonValueToUint16(value interface{}) uint16 {
	switch value := value.(type) {
	case string:
		v, _ := strconv.ParseUint(value, 10, 16)
		return uint16(v)
	case float32:
		return uint16(value)
	case float64:
		return uint16(value)
	case uint16:
		return value
	case uint32:
		return uint16(value)
	case uint64:
		return uint16(value)
	}
	return 0
}

func JsonValueToUint32(value interface{}) uint32 {
	switch value := value.(type) {
	case string:
		v, _ := strconv.ParseUint(value, 10, 32)
		return uint32(v)
	case float32:
		return uint32(value)
	case float64:
		return uint32(value)
	case uint32:
		return value
	case uint64:
		return uint32(value)
	}
	return 0
}

func JsonValueToInt32(value interface{}) int32 {
	switch value := value.(type) {
	case string:
		v, _ := strconv.ParseInt(value, 10, 32)
		return int32(v)
	case float32:
		return int32(value)
	case float64:
		return int32(value)
	case int32:
		return value
	case int64:
		return int32(value)
	}
	return 0
}

func JsonValueToUint64(value interface{}) uint64 {
	switch value := value.(type) {
	case string:
		v, _ := strconv.ParseUint(value, 10, 64)
		return v
	case float32:
		return uint64(value)
	case float64:
		return uint64(value)
	case uint32:
		return uint64(value)
	case uint64:
		return value
	}
	return 0
}

func JsonValueToInt(value interface{}) int {
	switch value := value.(type) {
	case string:
		v, _ := strconv.ParseInt(value, 10, 32)
		return int(v)
	case float32:
		return int(value)
	case float64:
		return int(value)
	case uint32:
		return int(value)
	case uint64:
		return int(value)
	case int:
		return value
	case int8:
		return int(value)
	case int16:
		return int(value)
	case int32:
		return int(value)
	case int64:
		return int(value)
	}
	return 0
}

func JsonValueToInt64(value interface{}) int64 {
	switch value := value.(type) {
	case string:
		v, _ := strconv.ParseInt(value, 10, 64)
		return v
	case float32:
		return int64(value)
	case float64:
		return int64(value)
	case int32:
		return int64(value)
	case int64:
		return value
	}
	return 0
}

func JsonValueToArray(value interface{}) []interface{} {
	switch value := value.(type) {
	case string:
		val := make([]interface{}, 0)
		_ = json.Unmarshal([]byte(value), &val)
		return val
	case []interface{}:
		return value
	}
	return []interface{}{}
}

func JsonValueToUint8Array(value interface{}) []uint8 {
	switch value := value.(type) {
	case string:
		val := make([]uint8, 0)
		_ = json.Unmarshal([]byte(value), &val)
		return val
	case []interface{}:
		val := make([]uint8, 0, len(value))
		for _, v := range value {
			val = append(val, JsonValueToUint8(v))
		}
		return val
	case []uint8:
		return value
	}
	return []uint8{}
}

func JsonValueToUint16Array(value interface{}) []uint16 {
	switch value := value.(type) {
	case string:
		val := make([]uint16, 0)
		_ = json.Unmarshal([]byte(value), &val)
		return val
	case []interface{}:
		val := make([]uint16, 0, len(value))
		for _, v := range value {
			val = append(val, JsonValueToUint16(v))
		}
		return val
	case []uint16:
		return value
	}
	return []uint16{}
}

func JsonValueToUint32Array(value interface{}) []uint32 {
	switch value := value.(type) {
	case string:
		val := make([]uint32, 0)
		_ = json.Unmarshal([]byte(value), &val)
		return val
	case []interface{}:
		val := make([]uint32, 0, len(value))
		for _, v := range value {
			val = append(val, JsonValueToUint32(v))
		}
		return val
	case []uint32:
		return value
	}
	return []uint32{}
}

func JsonValueToIntArray(value interface{}) []int {
	switch value := value.(type) {
	case string:
		val := make([]int, 0)
		if strings.TrimSpace(value) == "" {
			return val
		}
		_ = json.Unmarshal([]byte(value), &val)
		return val
	case []interface{}:
		val := make([]int, 0, len(value))
		for _, v := range value {
			val = append(val, JsonValueToInt(v))
		}
		return val
	case []int32:
		val := make([]int, 0, len(value))
		for _, v := range value {
			val = append(val, int(v))
		}
	case []int64:
		val := make([]int, 0, len(value))
		for _, v := range value {
			val = append(val, int(v))
		}
	case []int:
		return value
	}
	return []int{}
}

func JsonValueToBool(value interface{}) bool {
	if value == nil {
		return false
	}
	switch value := value.(type) {
	case string:
		t, _ := strconv.ParseBool(value)
		return t
	case bool:
		return value
	}
	return false
}
